// =============================================================
// CKeepAliveThread
// ---------------------------------------
// Author : Woo-Hyun Kim
// Email : woorung@icu.ac.kr or woorung@nhncorp.com
// Date : Oct. 8, 2007
// =============================================================
#include "CKeepAliveThread.h"
//----------------------------------------------------------------------
CKeepAliveThread::CKeepAliveThread(char *name) 
{
	setName(name);

	alive_max_time = 360;
	alive_time = 10;
	alive_min_time = alive_time;

	max_retry = 3;
	retry = 0;
}
//----------------------------------------------------------------------
CKeepAliveThread::~CKeepAliveThread() 
{
}
//----------------------------------------------------------------------
void CKeepAliveThread::keepalive(int ttl) 
{
	alive_time = ttl;
	alive_min_time = alive_time;
}
//----------------------------------------------------------------------
int CKeepAliveThread::keepalive() 
{
	return alive_time;
}
//----------------------------------------------------------------------
void CKeepAliveThread::bind(char *host, int port, CServiceRepository *container) 
{
	this->host = host;
	this->port = port;
	this->container = container;
}
//----------------------------------------------------------------------
void CKeepAliveThread::heartbeat() 
{
	CDiscoveryProxy proxy((char *)host.c_str(),port);

	// advertise
	if(proxy.advertise(container, alive_time)!=SOAP_OK) {
		alive_time *= 2;
		if(alive_time>=alive_max_time) alive_time = alive_max_time;
		
		retry++;
		if(retry>=max_retry) {
			cout << "ERROR : permanently not connected to server : " << host << ":" << port << endl;
			exit(-1);
		}
	}
	else {
		alive_time = alive_min_time;

		retry = 0;
	}
	
}
//----------------------------------------------------------------------
void CKeepAliveThread::monitor()
{
	CServiceProxy proxy;
	proxy.connect(container->getIP(), container->getPort());

	CObjectArray *pobjs = new CObjectArray(1);
	(*pobjs)[0] = new cube__CKeyValue();
	dynamic_cast<cube__CKeyValue*>((*pobjs)[0])->setKey(CUBE_SPACE_ACTION);
	dynamic_cast<cube__CKeyValue*>((*pobjs)[0])->setValue(CUBE_SPACE_SIZE);

	cube__CService space_service;
	space_service.service("sample.space.service");

	struct cube__invokeResponse res;

	// invoke
	if(proxy.invoke(&space_service, pobjs, res)!=SOAP_OK) {
		soap_print_fault(proxy.soap(), stderr);

		delete (*pobjs)[0];
		delete pobjs;

		return;
	}

	CObjectArray *array = dynamic_cast<CObjectArray *>(res.out);
	if(array==NULL) {
		cout << "what the heck~~" << endl;
	}

	cube__CKeyValue *kv = dynamic_cast<cube__CKeyValue *>(array->__ptr[0]);
	if(kv!=NULL) {
		int size = 0;
		if(strcmp(kv->getKey(),CUBE_SPACE_SIZE)==0) {
			size = atoi(kv->getValue());
//#ifdef DEBUG
			cout << "[" << container->getIP() << ":" << container->getPort() << "]current size = " << size << endl;
//#endif

		}
		else {
		}

	}

	delete (*pobjs)[0];
	delete pobjs;
}
//----------------------------------------------------------------------
void CKeepAliveThread::run() 
{
	string name = getName();

	while(1) {
		if(alive_time<0) break;

		try {
#ifdef DEBUG
			cout << "[" << getName() << "]keep-alive time = " << alive_time << endl;
#endif

			heartbeat();
//monitor();
			sleep(alive_time);
		} catch (InterruptedException& e) {
			cout << name << ": " << e.what();
			cout << " but continue" << endl;
		} catch(IllegalThreadStateException& ie) {
			cout << name << ": " << ie.what();
			cout << " but continue" << endl;
		}
	}

	cout << name << " ending" << endl;
}
//----------------------------------------------------------------------
